package org.jage.student.missevo.solution.workplace;

import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import org.jage.agent.IAgent;
import org.jage.platform.component.exception.ComponentException;
import org.jage.property.InvalidPropertyPathException;
import org.jage.student.missevo.solution.agent.MissEvoSimpleAgent;
import org.jage.student.missevo.solution.agent.MissEvoSimpleAggregate;
import org.jage.workplace.IsolatedSimpleWorkplace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MissEvoSimpleWorkplace extends IsolatedSimpleWorkplace {

	private static final long serialVersionUID = 1L;

	private final Logger log = LoggerFactory.getLogger(getClass());
	
	private long step;
	
	private SortedSet<Integer> agentKinds = new TreeSet<Integer>();
	
	private StringBuilder totalStatsBuilder = new StringBuilder();
	private SortedMap<String, StringBuilder> statsBuilders = new TreeMap<String, StringBuilder>();
	
	@Override
	public void step() {	
		if (step == 0) {
			discoverAgentKinds();
		}
		
		// total
		SortedMap<Integer, Integer> counts = new TreeMap<Integer, Integer>();
				
		for (IAgent iAggregate : getAgents()) {
			MissEvoSimpleAggregate aggregate = (MissEvoSimpleAggregate) iAggregate;
			for (IAgent iagent : aggregate.getAgents()) {
				MissEvoSimpleAgent agent = (MissEvoSimpleAgent)iagent;
				Integer kind = agent.getKind();
				Integer count = counts.get(kind);
				if (count != null) {
					counts.put(kind, count + 1);
				}
				else {
					counts.put(kind, 1);
				}
			}
		}
		
		totalStatsBuilder.append(step);
		for (Integer kind : agentKinds) {
			Integer count = counts.get(kind);
			//totalStatsBuilder.append(" " + kind + ":" + (count != null ? count : 0));
			totalStatsBuilder.append(" " + (count != null ? count : 0));
		}
		totalStatsBuilder.append("\n");
		
		// per island
		for (IAgent iAggregate : getAgents()) {
			MissEvoSimpleAggregate aggregate = (MissEvoSimpleAggregate) iAggregate;
			SortedMap<Integer, Integer> islandCounts = new TreeMap<Integer, Integer>();
			for (IAgent iagent : aggregate.getAgents()) {
				MissEvoSimpleAgent agent = (MissEvoSimpleAgent)iagent;
				Integer kind = agent.getKind();
				Integer count = islandCounts.get(kind);
				if (count != null) {
					islandCounts.put(kind, count + 1);
				}
				else {
					islandCounts.put(kind, 1);
				}
			}

			String aggregateName = (String) aggregate.getAddress().getName();
			StringBuilder islandStatsBuilder = statsBuilders.get(aggregateName);
			if (islandStatsBuilder == null) {
				islandStatsBuilder = new StringBuilder();
				statsBuilders.put(aggregateName, islandStatsBuilder);
			}
			islandStatsBuilder.append(step);
			for (Integer kind : agentKinds) {
				Integer count = islandCounts.get(kind);
				//islandStatsBuilder.append(" " + kind + ":" + (count != null ? count : 0));
				islandStatsBuilder.append(" " + (count != null ? count : 0));
			}
			islandStatsBuilder.append("\n");
		}
		
		
		
//		for (IAgent iagent : getAgents()) {
//			MissEvoSimpleAgent agent = (MissEvoSimpleAgent)iagent;
//			Integer kind = agent.getKind();
//			Integer count = counts.get(kind);
//			if (count != null) {
//				counts.put(kind, count++);
//			}
//			else {
//				counts.put(kind, 1);
//			}			
//		}
		super.step();
		step++;
	}
	
	private void discoverAgentKinds() {
		agentKinds.clear();
		for (IAgent iAggregate : getAgents()) {
			MissEvoSimpleAggregate aggregate = (MissEvoSimpleAggregate) iAggregate;
			for (IAgent iagent : aggregate.getAgents()) {
				MissEvoSimpleAgent agent = (MissEvoSimpleAgent)iagent;
				agentKinds.add(agent.getKind());
			}
		}
	}

	@Override
	public boolean finish() throws ComponentException {
		
		String stats = totalStatsBuilder.toString();
		System.out.println("total");
		System.out.println(stats);
		
		PrintWriter fileWriter = null;
		try {
			fileWriter = new PrintWriter("total.txt");
			fileWriter.print(stats);
		} catch (FileNotFoundException e) {
			log.error(e.getMessage());
		}
		finally {
			if (fileWriter != null) {
				fileWriter.close();
			}
		}
		
		for (Map.Entry<String, StringBuilder> entry : statsBuilders.entrySet()) {
			String name = entry.getKey();
			StringBuilder statsBuilder = entry.getValue();
			
			String islandStats = statsBuilder.toString();
			System.out.println(name);
			System.out.println(islandStats);
			
			PrintWriter islandFileWriter = null;
			try {
				islandFileWriter = new PrintWriter(name + ".txt");
				islandFileWriter.print(islandStats);
			} catch (FileNotFoundException e) {
				log.error(e.getMessage());
			}
			finally {
				if (islandFileWriter != null) {
					islandFileWriter.close();
				}
			}
		}
		
		return super.finish();
	}
	
}
